<?php

namespace app\admin\behavior;

use think\Log;
use think\Request;
use think\Exception;
use think\exception\HttpException;
use app\common\exception\RedirectException;
use think\facade\Session;
use think\Db;
use app\common\exception\NoAuthorizeException;
use think\exception\HttpResponseException;
use think\facade\Response;
use think\facade\Config;
use ReflectionClass;

/**
 *  run 方法在没有制定特别的标签名称 作为默认的执行方法体
 *  如果定义了制定标签的方法体 那么会执行同名的方法体
 */
// class AuthorizeFilter
// {
//     private $ignorePath = ['captcha', 'admin/account/login', 'admin/account/register', 'admin/account/forget'];
//     public function run(Request $request, $params)
//     {
//         if (!in_array($request->path(), $this->ignorePath)) {
//             $urls = Session::get('urls');
//             $result =  in_array($request->url(), $urls);
//             if (!$result) {
//                 if ($request->isAjax()) {
//                     throw new NoAuthorizeException();
//                 }
//             }
//         }
//     }
// }
class AuthorizeFilter
{
    static $authorize_regex="/^@authorize\('.+'\)$/i";
    static $authorize_replace="/^@authorize\('(.+)'\)$/i";
    static $allow_regex="/^@allow$/i";

    private $ignorePath = ['captcha', 'admin/account/login', 'admin/account/register', 'admin/account/forget'];
    public function run(Request $request, $params)
    {
        $items=$params[0];
        $class=new ReflectionClass($items);

        $allow=true;

        $actionMethod=$class->getMethod($request->action());

        if(!$this->findAtrribute($actionMethod,self::$allow_regex))
        {
            $attribute=$this->findAtrribute($actionMethod,self::$authorize_regex);
            if($attribute)
            {
                //在 action上找是否开启了权限
                $allow=$this->checkAuthorize($attribute);
            }
            else
            {
                //在Controller上找是否开启了权限
                $attribute=$this->findAtrribute($class,self::$authorize_regex);
                $allow=$this->checkAuthorize($attribute);
            }
        }

        if(!$allow) throw new NoAuthorizeException();
    }

    /**
     * 找到注释
     *
     * @param [type] $class
     * @param [type] $pattern  正则匹配注释
     * @return void
     */
    private function findAtrribute($class,$pattern){
        $attribute=$class->getDocComment();
        $attribute=explode("*",$attribute);
        $attribute=array_filter($attribute,function($item) use($pattern){
            $item=trim($item);
            if(preg_match($pattern,$item)){
                return true;
            }
           return false;
        });
        if(count($attribute)>0) return trim(array_pop($attribute));
        return null;
    }
    
    /**
     * 判断注释上的权限用户是否拥有
     *
     * @param [type] $attribute
     * @return void
     */
    private function checkAuthorize($attribute){
        if(empty($attribute)) return true;

        $item=$attribute;
        $item=preg_replace(self::$authorize_replace, "$1", $item);
        if(empty($item)) return true;//只需要用户登录

        $permissions=Session::get('permissions'); 
        if(empty($permissions)) return false; //当用户没有权限列表，而action设置了权限时 不通过

        return in_array($item, $permissions);
    }
}
